package ink.tiptop.utils.ssh;

import com.trilead.ssh2.Connection;
import com.trilead.ssh2.Session;
import lombok.extern.slf4j.Slf4j;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

/**
 * @author tiptop_zjf
 * @ClassName: SshTest
 * @DESC 可用ssh工具 2020年1月3日10:06:50 zjf
 * @Date: 2020/1/3 9:51
 * @since JDK 1.8
 */
@Slf4j
public class SshUtil {

    public static Connection connect(SshInfo remote) throws IOException {
        Connection conn = null;
        try {
            conn = connectByRight(remote);
        } catch (Exception e) {
            log.error("connect connect connect connect");
            throw e;
        }
        return conn;
    }

    private static Connection connectByRight(SshInfo remote) throws IOException {
        Connection conn = null;
        try {
            // 先采用密钥方式登陆
            conn = new Connection(remote.getHost(), remote.getPort());
            conn.connect();
            if (isPasswordConn(remote)) {
                conn.authenticateWithPassword(remote.getUsername(), remote.getPassword());
            } else if (isPrivateKeyConn(remote)) {
                boolean auth = conn.authenticateWithPublicKey(remote.getUsername(), remote.getIdentity().toCharArray(), remote.getPassphrase());
                if (!auth) {
                    conn.authenticateWithPassword(remote.getUsername(), remote.getPassword());
                }
            } else {
                throw new IOException("配置连接错误");
            }
        } catch (IllegalStateException | IllegalArgumentException e) {
            log.error("可能是连接方式选择错误");
        } catch (Exception e) {
            log.error("可能是连接方式选择错误2");
            e.printStackTrace();
            throw e;
        }
        return conn;
    }

    private static boolean isPasswordConn(SshInfo remote) {
        return remote.getPassword() != null;
    }

    private static boolean isPrivateKeyConn(SshInfo remote) {
        return remote.getIdentity() != null;
    }

    public static String input() {
        InputStreamReader is = null;
        BufferedReader br = null;
        String dir = null;
        try {
            is = new InputStreamReader(System.in);
            br = new BufferedReader(is);
            dir = br.readLine().trim();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // TODO 千万不能关闭,不然不能获取到下次的键盘输入
        }
        return dir == null ? "" : dir;
    }


    public static List<String> refreshConnection(Connection conn, String command) throws Exception {
        List<String> resultLines = new ArrayList<>();
        Session session = null;
        try {
            session = conn.openSession();
            session.execCommand(command);
            BufferedReader inputReader = new BufferedReader(new InputStreamReader(session.getStdout()));
            String inputLine = null;
            while ((inputLine = inputReader.readLine()) != null) {
                resultLines.add(inputLine);
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        } finally {
            try {
                if (session != null) {
                    session.close();
                }
            } catch (Exception e) {
                log.error("JSch channel disconnect error:", e);
            }
        }
        return resultLines;
    }

    public static List<String> exec(Connection conn, String command) throws Exception {
        List<String> resultLines = new ArrayList<>();
        Session session = null;
        try {
            session = conn.openSession();
            session.execCommand(command);
            BufferedReader inputReader = new BufferedReader(new InputStreamReader(session.getStdout()));
            String inputLine = null;
            while ((inputLine = inputReader.readLine()) != null) {
                resultLines.add(inputLine);
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        } finally {
            try {
                if (session != null) {
                    session.close();
                }
            } catch (Exception e) {
                log.error("JSch channel disconnect error:", e);
            }
        }
        return resultLines;
    }

}
